package com.mzj.saas.sdk.pay.wxpay;

import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.HttpUtil;

import com.alibaba.fastjson.JSON;
import com.mzj.saas.sdk.pay.vo.WxPay;
import com.mzj.saas.sdk.util.WechatUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 微信支付类
 *
 * @author hp
 *
 */
public class WxPayRequest {

	private final static Logger logger = LoggerFactory.getLogger(WxPayRequest.class);

	private WxPay wxPay;

	public WxPayRequest(final WxPay wxPay){
		this.wxPay = wxPay;
	}

	/**
	 * APP支付统一下单
	 * <p>
	 * 微信APP支付接口文档地址：https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
	 * </p>
	 *
	 * @return null为失败，成功则返回前端调起支付所属参数
	 */
	public Map<String, Object> unifiedByApp() {

		if (wxPay == null) {
			logger.error("APP支付统一下单---------->wxPay is null");
			return null;
		}
		String nonceStr = WechatUtils.generateNonceStr();
		SortedMap<String, Object> paramsMap = new TreeMap<String, Object>();
		paramsMap.put("appid", wxPay.getAppId());
		paramsMap.put("mch_id", wxPay.getMchId());
		paramsMap.put("nonce_str", nonceStr);
		paramsMap.put("sign_type", "MD5");
		paramsMap.put("body", wxPay.getBody());
		paramsMap.put("attach", wxPay.getAttach());
		paramsMap.put("out_trade_no", wxPay.getOutTradeNo());
		paramsMap.put("total_fee", wxPay.getTotalFee());
		paramsMap.put("spbill_create_ip", wxPay.getSpbillCreateIp());
		paramsMap.put("notify_url", wxPay.getCallbackUrl());
		paramsMap.put("trade_type", "APP");

		// 请求参数签名
		String sign = WechatUtils.getSign(paramsMap, wxPay.getMchApiKey());
		paramsMap.put("sign", sign);
		// 请求参数转成xml字符串
		String xmlParams = XmlUtil.mapToXmlStr(paramsMap);
		logger.warn("APP支付统一下单, 支付参数：{}", JSON.toJSONString(xmlParams));
		// 微信统一下单
		String response = HttpUtil.post(wxPay.getUnifiedApi(), xmlParams);
		Map<String, Object> responseMap = XmlUtil.xmlToMap(response);
		if (responseMap == null || responseMap.isEmpty()) {
			logger.error("APP支付统一下单---------->返回结果xml解析失败！response=[{}]", response);
			return null;
		}

		if ("SUCCESS".equals(responseMap.get("result_code")) && "SUCCESS".equals(responseMap.get("return_code"))) {
			String prepayid = responseMap.get("prepay_id").toString();

			SortedMap<String, Object> paymentUpParamMap = new TreeMap<String, Object>();
			// APP前端调起支付所属参数
			paymentUpParamMap.put("appid", wxPay.getAppId());
			paymentUpParamMap.put("partnerid", wxPay.getMchId());
			paymentUpParamMap.put("prepayid", prepayid);
			paymentUpParamMap.put("package", "Sign=WXPay");
			paymentUpParamMap.put("noncestr", nonceStr);
			paymentUpParamMap.put("timestamp", System.currentTimeMillis() / 1000);
			// 请求参数签名
			String paySign = WechatUtils.getSign(paymentUpParamMap, wxPay.getMchApiKey());
			paymentUpParamMap.put("sign", paySign);

			return paymentUpParamMap;
		}
		logger.error("APP支付统一下单----------> [outTradeNo={}]微信支付失败！微信返回结果：{}", wxPay.getOutTradeNo(), response);
		return null;
	}

	/**
	 * 扫码支付统一下单
	 * <p>
	 * 微信APP支付接口文档地址：https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
	 * </p>
	 *
	 * @return null为失败，成功则返回前端调起支付所属参数
	 */
	public Map<String, Object> unifiedByNative() {

		if (wxPay == null) {
			logger.error("扫码支付统一下单---------->wxPay is null");
			return null;
		}
		String nonceStr = WechatUtils.generateNonceStr();
		SortedMap<String, Object> paramsMap = new TreeMap<String, Object>();
		paramsMap.put("appid", wxPay.getAppId());
		paramsMap.put("mch_id", wxPay.getMchId());
		paramsMap.put("nonce_str", nonceStr);
		paramsMap.put("sign_type", "MD5");
		paramsMap.put("body", wxPay.getBody());
		paramsMap.put("attach", wxPay.getAttach());
		paramsMap.put("out_trade_no", wxPay.getOutTradeNo());
		paramsMap.put("total_fee", wxPay.getTotalFee());
		paramsMap.put("spbill_create_ip", wxPay.getSpbillCreateIp());
		paramsMap.put("notify_url", wxPay.getCallbackUrl());
		paramsMap.put("trade_type", "NATIVE");

		// 请求参数签名
		String sign = WechatUtils.getSign(paramsMap, wxPay.getMchApiKey());
		paramsMap.put("sign", sign);
		// 请求参数转成xml字符串
		String xmlParams = XmlUtil.mapToXmlStr(paramsMap);

		// 微信统一下单
		String response = HttpUtil.post(wxPay.getUnifiedApi(), xmlParams);
		Map<String, Object> responseMap = XmlUtil.xmlToMap(response);
		if (responseMap == null || responseMap.isEmpty()) {
			logger.error("扫码支付统一下单---------->返回结果xml解析失败！response=[{}]", response);
			return null;
		}

		if ("SUCCESS".equals(responseMap.get("result_code")) && "SUCCESS".equals(responseMap.get("return_code"))) {
			String prepayid = responseMap.get("prepay_id").toString();
			String codeUrl = responseMap.get("code_url").toString();

			SortedMap<String, Object> paymentUpParamMap = new TreeMap<String, Object>();
			// APP前端调起支付所属参数
			paymentUpParamMap.put("appid", wxPay.getAppId());
			paymentUpParamMap.put("partnerid", wxPay.getMchId());
			paymentUpParamMap.put("prepayid", prepayid);
			paymentUpParamMap.put("package", "Sign=WXPay");
			paymentUpParamMap.put("noncestr", nonceStr);
			paymentUpParamMap.put("timestamp", System.currentTimeMillis() / 1000);
			// 请求参数签名
			String paySign = WechatUtils.getSign(paymentUpParamMap, wxPay.getMchApiKey());
			paymentUpParamMap.put("sign", paySign);
			//二维码链接
			paymentUpParamMap.put("codeUrl", codeUrl);
			paymentUpParamMap.put("outTradeNo", wxPay.getOutTradeNo());
			paymentUpParamMap.put("mchid", wxPay.getMchId());
			paymentUpParamMap.put("mchApiKey", wxPay.getMchApiKey());
			return paymentUpParamMap;
		}
		logger.error("扫码支付统一下单----------> [outTradeNo={}]微信支付失败！微信返回结果：{}", wxPay.getOutTradeNo(), response);
		return null;
	}

	/**
	 * 小程序支付统一下单
	 * <p>
	 * 微信小程序支付接口文档地址：https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
	 * </p>
	 *
	 * @return null为失败，成功则返回前端调起支付所属参数
	 */
	public Map<String, Object> unifiedByMini() {

		if (wxPay == null || StringUtils.isBlank(wxPay.getOpenid())) {
			logger.error("小程序支付统一下单---------->wxPay is null or openid is null");
			return null;
		}
		String nonceStr = WechatUtils.generateNonceStr();
		SortedMap<String, Object> paramsMap = new TreeMap<String, Object>();
		paramsMap.put("appid", wxPay.getAppId());
		paramsMap.put("mch_id", wxPay.getMchId());
		paramsMap.put("nonce_str", nonceStr);
		paramsMap.put("sign_type", "MD5");
		paramsMap.put("body", wxPay.getBody());
		paramsMap.put("attach", wxPay.getAttach());
		paramsMap.put("out_trade_no", wxPay.getOutTradeNo());
		paramsMap.put("total_fee", wxPay.getTotalFee());
		paramsMap.put("spbill_create_ip", wxPay.getSpbillCreateIp());
		paramsMap.put("notify_url", wxPay.getCallbackUrl());
		paramsMap.put("openid", wxPay.getOpenid());
		paramsMap.put("trade_type", "JSAPI");
		// 请求参数签名
		String sign = WechatUtils.getSign(paramsMap, wxPay.getMchApiKey());
		paramsMap.put("sign", sign);
		// 请求参数转成xml字符串
		String xmlParams = XmlUtil.mapToXmlStr(paramsMap);

		// 微信统一下单
		String response = HttpUtil.post(wxPay.getUnifiedApi(), xmlParams);
		Map<String, Object> responseMap = XmlUtil.xmlToMap(response);
		if (responseMap == null || responseMap.isEmpty()) {
			logger.error("小程序支付统一下单---------->返回结果xml解析失败！response=[{}]", response);
			return null;
		}

		if ("SUCCESS".equals(responseMap.get("result_code")) && "SUCCESS".equals(responseMap.get("return_code"))) {
			String prepayid = responseMap.get("prepay_id").toString();

			SortedMap<String, Object> paymentUpParamMap = new TreeMap<String, Object>();
			paymentUpParamMap.put("appId", wxPay.getAppId());
			paymentUpParamMap.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
			paymentUpParamMap.put("nonceStr", nonceStr);
			paymentUpParamMap.put("package", "prepay_id=" + prepayid);
			paymentUpParamMap.put("signType", "MD5");
			// 请求参数签名
			String paySign = WechatUtils.getSign(paymentUpParamMap, wxPay.getMchApiKey());
			paymentUpParamMap.put("paySign", paySign);

			return paymentUpParamMap;
		}
		logger.error("小程序支付统一下单----------> [outTradeNo={}]微信支付失败！微信返回结果：{}", wxPay.getOutTradeNo(), response);
		return null;
	}

	/**
	 * 查询订单
	 *
	 * @return
	 */
	public Map<String, Object> orderQuery() {
		if (wxPay == null) {
			logger.error("查询订单---------->wxPay is null");
			return null;
		}

		SortedMap<String, Object> paramsMap = new TreeMap<String, Object>();
		paramsMap.put("appid", wxPay.getAppId());
		paramsMap.put("mch_id", wxPay.getMchId());
		paramsMap.put("out_trade_no", wxPay.getOutTradeNo());
		String nonceStr = WechatUtils.generateNonceStr();
		paramsMap.put("nonce_str", nonceStr);
		// 请求参数签名
		String sign = WechatUtils.getSign(paramsMap, wxPay.getMchApiKey());
		paramsMap.put("sign", sign);
		// 请求参数转成xml字符串
		String xmlParams = XmlUtil.mapToXmlStr(paramsMap);

		String response = HttpUtil.post(wxPay.getUnifiedApi(), xmlParams);
		Map<String, Object> responseMap = XmlUtil.xmlToMap(response);
		if (responseMap == null || responseMap.isEmpty()) {
			logger.error("查询订单---------->返回结果xml解析失败！response=[{}]", response);
			return null;
		}

		if ("SUCCESS".equals(responseMap.get("result_code")) && "SUCCESS".equals(responseMap.get("return_code"))) {
			String tradeState = responseMap.get("trade_state").toString();

			SortedMap<String, Object> paymentUpParamMap = new TreeMap<String, Object>();
			if("SUCCESS".equals(tradeState)){
				paymentUpParamMap.put("tradeState", "SUCCESS");
			}else {
				paymentUpParamMap.put("tradeState", "FAIL");
			}
			return paymentUpParamMap;
		}

		logger.error("查询订单----------> [outTradeNo={}]微信查询订单失败！微信返回结果：{}", wxPay.getOutTradeNo(), response);
		return null;
	}




}
